using System.IO;

using System.Management.Automation;

using Microsoft.PowerShell.Commands;

using Pscx.Commands.IO.Compression.ArchiveReader;
using Pscx.IO;

namespace Pscx.Commands.IO.Compression
{
    /// <summary>
    /// Enumerates archives and writes an object for each distinct entry in the archive.
    /// </summary>
	[Cmdlet(VerbsCommunications.Read, PscxNouns.Archive,
        DefaultParameterSetName = ParameterSetPath)]
    [ProviderConstraint(typeof(FileSystemProvider))]
    public class ReadArchiveCommand : PscxInputObjectPathCommandBase
	{
        public ReadArchiveCommand()
        {
            this.Format = ArchiveFormat.Unknown;
        }

        [Parameter(Position = 0, ParameterSetName = ParameterSetObject)]
        [Parameter(Position = 1, ParameterSetName = ParameterSetPath)]
        public ArchiveFormat Format { get; set; }

        /// <summary>
        /// Show progress for reading archives.
        /// </summary>
        [Parameter]
        public SwitchParameter ShowProgress { get; set; }

        /// <summary>
        /// If present, write out an ArchiveEntry object for each directory/folder entry in the archive.
        /// </summary>
        [Parameter]
        public SwitchParameter IncludeDirectories { get; set; }

        protected override bool OnValidatePscxPath(string parameterName, IPscxPathSettings settings)
        {
            if (parameterName == "LiteralPath")
            {
                settings.ShouldExist = true;
            }
            return true;
        }

        protected override void BeginProcessing()
        {
            base.BeginProcessing();

            RegisterInputType<FileInfo>(ProcessArchive);
            RegisterPathInputType<FileInfo>();
        }

        protected virtual void ProcessArchive(FileInfo archive)
        {
            ArchiveFormat format = this.Format;
            
            if ((format != ArchiveFormat.Unknown) ||
                SevenZipBase.TryGetFormat(this, archive, ref format))
            {
                using (var reader = new SevenZipReader(this, archive, format))
                {
                    reader.ShowScanProgress = ShowProgress;

                    foreach (ArchiveEntry entry in reader)
                    {
                        // only dump out the zero-length folder entries
                        // if instructed to.
                        if (this.IncludeDirectories || !entry.IsFolder)
                        {
                            WriteObject(entry);
                        }
                    }
                }
            }
            else
            {
                // todo: localize
                // unknown file extension / format and no -Format override specified
                ErrorHandler.HandleError(true,
                    new ErrorRecord(new PSArgumentException("Unknown file extension or invalid archive. You may override the format used with the -Format parameter."),
                        "UnknownArchiveFormat", ErrorCategory.ReadError, archive));
            }
        }

        protected override void ProcessPath(PscxPathInfo pscxPath)
        {
            var archive = new FileInfo(pscxPath.ProviderPath);
            ProcessArchive(archive);
        }
    }
}
